package nf.utility;

import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import nf.util.Rational;
import nf.OrganizationalGroup;
import nf.graph.Node;
import nf.graph.Graph;
import nf.graph.Group;
import nf.graph.Path;
import nf.graph.PropertyBag;

public abstract class UtilityCalculator
{
	private Set<UtilityTracer> tracers;

	public Rational getUtility(Graph graph, Node node)
	{
		Map<Node, Rational> utilities = getUtilities(graph);
		return utilities.get(node);
	}
	
	public abstract Map<Node, Rational> getUtilities(Graph graph);
	
	private void createTracerSet()
	{
		if (tracers == null)
			tracers = new HashSet<UtilityTracer>();
	}
	
	public boolean addTracer(UtilityTracer tracer)
	{
		createTracerSet();
		return tracers.add(tracer);
	}
	
	public boolean removeTracer(UtilityTracer tracer)
	{
		createTracerSet();
		return tracers.remove(tracer);
	}
	
	protected void traceValue(Node node, Rational value, Node pathHead,
		Node pathTail)
	{
		if (tracers == null)
			return;
		
		for (UtilityTracer t : tracers) {
			t.traceValue(node, value, pathHead, pathTail);
		}
	}
	
	protected Rational getEdgeCost(Node head, Node tail)
	{
		Group commonGroup = head.enclosingGroup(tail);
		
		try {
			return ((OrganizationalGroup) commonGroup).getEdgeCost();
		} catch (ClassCastException e) {
			return (Rational) PropertyBag.Access.get(commonGroup, "edgeCost");
		}
	}
}
